package com.scale.service.voice.service.impl;

import com.example.conversation.dto.SendMessageDTO;
import com.example.conversation.vo.MessageVO;
import com.example.voice.dto.ProcessMessageDTO;
import com.example.voice.dto.SpeechToTextDTO;
import com.example.voice.dto.TextToSpeechDTO;
import com.example.voice.dto.UploadUserAudioDTO;
import com.example.voice.vo.SpeechToTextVO;
import com.example.voice.vo.TextToSpeechVO;
import com.example.voice.vo.UploadUserAudioVO;
import com.scale.service.conversation.service.MessagesService;
import com.scale.service.voice.service.VoiceProcessService;
import com.alibaba.dashscope.aigc.multimodalconversation.AudioParameters;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.scale.service.voice.service.VoiceFileStorageService;
import com.scale.service.conversation.service.MessagesService;
import com.example.conversation.entity.Messages;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 语音处理服务实现类
 * @author crp
 * @since 2025-09-24
 */
@Service
public class VoiceProcessServiceImpl implements VoiceProcessService {

    @Autowired
    private MessagesService messagesService;
    
    @Autowired
    private VoiceFileStorageService voiceFileStorageService;
    
    @Value("${dashscope.api-key:}")
    private String dashscopeApiKey;

    @Override
    public SpeechToTextVO speechToText(SpeechToTextDTO speechToTextDTO) {
        long startTime = System.currentTimeMillis();

        try {
        // 输入验证
            if (speechToTextDTO.getAudioData() == null || speechToTextDTO.getAudioData().trim().isEmpty()) {
                throw new Exception("音频数据不能为空");
            }

            // 设置默认语言为中文
            if (speechToTextDTO.getLanguage() == null || speechToTextDTO.getLanguage().isEmpty()) {
                speechToTextDTO.setLanguage("zh");
            }
            
            // 使用阿里云通义千问3-ASR-Flash进行语音识别
            SpeechToTextVO result = callAlibabaASR(speechToTextDTO);
            result.setProcessTime((int)(System.currentTimeMillis() - startTime));
            
            // 验证识别结果
            if (result.getText() == null || result.getText().trim().isEmpty()) {
                System.err.println("ASR识别结果为空，可能是音频格式不支持或API调用失败");
                return createMockSpeechResult(speechToTextDTO, startTime, "识别结果为空");
            }
            
            return result;
        } catch (Exception e) {
            // 如果调用失败，返回模拟结果（作为降级方案）
            System.err.println("阿里云ASR调用失败: " + e.getMessage());
            e.printStackTrace();
            return createMockSpeechResult(speechToTextDTO, startTime, e.getMessage());
        }
    }

    /**
     * 调用阿里云通义千问3-ASR-Flash进行语音识别
     */
    private SpeechToTextVO callAlibabaASR(SpeechToTextDTO speechToTextDTO) throws Exception {
        try {
            MultiModalConversation conv = new MultiModalConversation();

            // 处理音频数据
            String audioContent = processAudioData(speechToTextDTO.getAudioData());
            
            // 构建用户消息（包含音频）
            MultiModalMessage userMessage = MultiModalMessage.builder()
                    .role(Role.USER.getValue())
                    .content(Arrays.asList(
                            Collections.singletonMap("audio", audioContent)))
                    .build();

            // 系统消息（可用于定制化识别）
            MultiModalMessage sysMessage = MultiModalMessage.builder()
                    .role(Role.SYSTEM.getValue())
                    .content(Arrays.asList(Collections.singletonMap("text", "")))
                    .build();

            // ASR选项配置
            Map<String, Object> asrOptions = new HashMap<>();
            asrOptions.put("enable_lid", true); // 启用语言识别
            asrOptions.put("enable_itn", true); // 启用逆文本规范化（数字、时间等标准化）
            asrOptions.put("enable_punctuation", true); // 启用标点符号
            asrOptions.put("enable_timestamp", false); // 关闭时间戳
            
            // 根据语言设置 - 修复语言代码映射
            String language = speechToTextDTO.getLanguage();
            if (language != null) {
                if (language.startsWith("zh") || "zh".equals(language)) {
                    asrOptions.put("language", "zh"); // 阿里云支持的语言代码
                } else if (language.startsWith("en") || "en".equals(language)) {
                    asrOptions.put("language", "en"); // 英文
                } else {
                    asrOptions.put("language", "zh"); // 默认中文
                }
            } else {
                asrOptions.put("language", "zh"); // 默认中文
            }

            // 检查API密钥
            String apiKey = getApiKey();
            if (apiKey == null || apiKey.trim().isEmpty()) {
                throw new Exception("API密钥未配置，请设置DASHSCOPE_API_KEY环境变量");
            }

            MultiModalConversationParam param = MultiModalConversationParam.builder()
                    .apiKey(apiKey)
                    .model("qwen3-asr-flash")
                    .message(userMessage)
                    .message(sysMessage)
                    .parameter("asr_options", asrOptions)
                    .build();

            MultiModalConversationResult result = conv.call(param);

            // 解析结果
            SpeechToTextVO speechResult = new SpeechToTextVO();
            String recognizedText = extractTextFromResult(result);
            speechResult.setText(recognizedText);
            speechResult.setConfidence(BigDecimal.valueOf(0.95)); // ASR-Flash通常有很高的准确率
            speechResult.setDuration(calculateAudioDuration(speechToTextDTO.getAudioData()));

            // 如果启用了情绪检测（可选功能）
            if (speechToTextDTO.getEnableEmotionDetection()) {
                // 这里可以集成情绪分析API或使用简单的关键词分析
                analyzeEmotion(speechResult);
            }

            return speechResult;

        } catch (ApiException | NoApiKeyException | UploadFileException e) {
            System.err.println("阿里云ASR调用失败: " + e.getMessage());
            
            // 提供更详细的错误信息
            String errorMessage = "语音识别失败: " + e.getMessage();
            if (e.getMessage().contains("InvalidParameter")) {
                if (e.getMessage().contains("Language code")) {
                    errorMessage = "语音识别失败: 语言代码不支持，请检查语言设置";
                } else if (e.getMessage().contains("audio")) {
                    errorMessage = "语音识别失败: 音频格式不支持，请使用WAV、MP3或M4A格式";
                } else {
                    errorMessage = "语音识别失败: 参数错误，请检查音频格式和语言设置";
                }
            } else if (e.getMessage().contains("Unauthorized")) {
                errorMessage = "语音识别失败: API密钥无效，请检查配置";
            } else if (e.getMessage().contains("QuotaExceeded")) {
                errorMessage = "语音识别失败: API调用次数超限，请稍后重试";
            }
            
            throw new Exception(errorMessage, e);
        }
    }

    /**
     * 从ASR结果中提取识别的文本
     */
    private String extractTextFromResult(MultiModalConversationResult result) {
        if (result != null && result.getOutput() != null && result.getOutput().getChoices() != null) {
            try {
                String content = result.getOutput().getChoices().get(0).getMessage().getContent().toString();
                // 解析JSON格式的内容，提取text字段
                if (content.contains("\"text\"")) {
                    int textStart = content.indexOf("\"text\":\"") + 8;
                    int textEnd = content.indexOf("\"", textStart);
                    if (textStart > 7 && textEnd > textStart) {
                        return content.substring(textStart, textEnd);
                    }
                }
                return content;
            } catch (Exception e) {
                System.err.println("解析ASR结果失败: " + e.getMessage());
                return "识别失败";
            }
        }
        return "识别失败";
    }

    /**
     * 计算音频时长（简单估算）
     */
    private BigDecimal calculateAudioDuration(String audioData) {
        // 简单估算：Base64编码的音频数据长度大致对应时长
        // 实际项目中可以使用音频处理库获取准确时长
        if (audioData != null && audioData.length() > 1000) {
            // 粗略估算：每1000个字符大约对应0.1秒
            return BigDecimal.valueOf(audioData.length() / 10000.0);
        }
        return BigDecimal.valueOf(3.0); // 默认3秒
    }

    /**
     * 分析语音情绪（简单实现）
     */
    private void analyzeEmotion(SpeechToTextVO speechResult) {
        String text = speechResult.getText();
        if (text != null) {
            // 简单的关键词情绪分析
            if (text.contains("开心") || text.contains("高兴") || text.contains("哈哈")) {
                speechResult.setEmotionType("happy");
                speechResult.setEmotionIntensity(BigDecimal.valueOf(0.8));
            } else if (text.contains("难过") || text.contains("伤心") || text.contains("哭")) {
                speechResult.setEmotionType("sad");
                speechResult.setEmotionIntensity(BigDecimal.valueOf(0.7));
            } else if (text.contains("生气") || text.contains("愤怒") || text.contains("烦")) {
                speechResult.setEmotionType("angry");
                speechResult.setEmotionIntensity(BigDecimal.valueOf(0.6));
            } else {
            speechResult.setEmotionType("neutral");
            speechResult.setEmotionIntensity(BigDecimal.valueOf(0.5));
            }
        }
    }

    /**
     * 创建模拟语音识别结果（降级方案）
     */
    private SpeechToTextVO createMockSpeechResult(SpeechToTextDTO speechToTextDTO, long startTime, String errorMessage) {
        SpeechToTextVO result = new SpeechToTextVO();
        
        // 根据错误类型返回不同的提示信息
        String mockText;
        if (errorMessage != null && errorMessage.contains("API密钥")) {
            mockText = "语音识别服务配置错误，请检查API密钥配置。";
        } else if (errorMessage != null && errorMessage.contains("网络")) {
            mockText = "网络连接异常，语音识别服务暂时不可用。";
        } else if (errorMessage != null && errorMessage.contains("格式")) {
            mockText = "音频格式不支持，请尝试使用WAV或MP3格式。";
        } else {
            mockText = "语音识别服务暂时不可用，请稍后重试。";
        }
        
        result.setText(mockText);
        result.setConfidence(BigDecimal.valueOf(0.0)); // 明确标识为模拟数据
        result.setDuration(BigDecimal.valueOf(3.5));
        result.setProcessTime((int)(System.currentTimeMillis() - startTime));
        result.setIsMock(true); // 添加标识字段

        // 如果启用了情绪检测
        if (speechToTextDTO.getEnableEmotionDetection()) {
            result.setEmotionType("neutral");
            result.setEmotionIntensity(BigDecimal.valueOf(0.6));
        }

        return result;
    }

    @Override
    public TextToSpeechVO textToSpeech(TextToSpeechDTO textToSpeechDTO) {
        long startTime = System.currentTimeMillis();

        try {
            // 输入验证
            if (textToSpeechDTO.getText() == null || textToSpeechDTO.getText().trim().isEmpty()) {
                throw new Exception("要转换的文本不能为空");
            }

            // 设置默认参数
            if (textToSpeechDTO.getVoiceType() == null || textToSpeechDTO.getVoiceType().isEmpty()) {
                textToSpeechDTO.setVoiceType("female");
            }
            if (textToSpeechDTO.getSpeed() == null) {
                textToSpeechDTO.setSpeed(BigDecimal.valueOf(1.0));
            }
            if (textToSpeechDTO.getPitch() == null) {
                textToSpeechDTO.setPitch(BigDecimal.valueOf(1.0));
            }
            if (textToSpeechDTO.getEmotion() == null || textToSpeechDTO.getEmotion().isEmpty()) {
                textToSpeechDTO.setEmotion("neutral");
            }
            if (textToSpeechDTO.getFormat() == null || textToSpeechDTO.getFormat().isEmpty()) {
                textToSpeechDTO.setFormat("wav");
            }

            // 使用阿里云通义千问3-TTS-Flash进行语音合成
            TextToSpeechVO result = callAlibabaTTS(textToSpeechDTO);
            result.setProcessTime((int)(System.currentTimeMillis() - startTime));
            
            // 验证结果
            if (result.getAudioUrl() == null || result.getAudioUrl().trim().isEmpty()) {
                System.err.println("TTS生成结果为空，使用降级方案");
                return createMockTTSResult(textToSpeechDTO, startTime);
            }
            
            return result;
        } catch (Exception e) {
            // 如果调用失败，返回模拟结果（作为降级方案）
            System.err.println("阿里云TTS调用失败: " + e.getMessage());
            e.printStackTrace();
            return createMockTTSResult(textToSpeechDTO, startTime);
        }
    }
    
    /**
     * 调用阿里云通义千问3-TTS-Flash进行语音合成
     */
    private TextToSpeechVO callAlibabaTTS(TextToSpeechDTO textToSpeechDTO) throws Exception {
        try {
            MultiModalConversation conv = new MultiModalConversation();
            
            // 根据用户设置选择音色
            AudioParameters.Voice voice = getVoiceByType(textToSpeechDTO.getVoiceType());
            
            // 根据文本语言设置语言类型
            String languageType = detectLanguageType(textToSpeechDTO.getText());
            
            // 检查API密钥
            String apiKey = getApiKey();
            if (apiKey == null || apiKey.trim().isEmpty()) {
                throw new Exception("API密钥未配置，请设置DASHSCOPE_API_KEY环境变量");
            }

            MultiModalConversationParam param = MultiModalConversationParam.builder()
                    .apiKey(apiKey)
                    .model("qwen3-tts-flash")
                    .text(textToSpeechDTO.getText())
                    .voice(voice)
                    .languageType(languageType)
                    .build();

            MultiModalConversationResult result = conv.call(param);
            
            if (result != null && result.getOutput() != null && result.getOutput().getAudio() != null) {
                String audioUrl = result.getOutput().getAudio().getUrl();
                
                // 下载音频文件到本地存储
                String localAudioUrl = downloadAndStoreAudio(audioUrl, textToSpeechDTO.getFormat());
                
                // 构建返回结果
                TextToSpeechVO ttsResult = new TextToSpeechVO();
                ttsResult.setAudioUrl(localAudioUrl);
                ttsResult.setFormat(textToSpeechDTO.getFormat());
                ttsResult.setDuration(estimateAudioDuration(textToSpeechDTO.getText()));
                
                return ttsResult;
            } else {
                throw new Exception("TTS结果为空");
            }
            
        } catch (ApiException | NoApiKeyException | UploadFileException e) {
            System.err.println("阿里云TTS调用失败: " + e.getMessage());
            throw new Exception("语音合成失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 根据音色类型获取阿里云音色参数
     */
    private AudioParameters.Voice getVoiceByType(String voiceType) {
        if (voiceType == null) {
            return AudioParameters.Voice.CHERRY; // 默认音色
        }
        
        switch (voiceType.toLowerCase()) {
            case "male":
            case "男声":
                return AudioParameters.Voice.DYLAN; // 男声
            case "female":
            case "女声":
            default:
                return AudioParameters.Voice.CHERRY; // 女声（默认）
            case "child":
            case "童声":
                return AudioParameters.Voice.JADA; // 童声
            case "sunny":
            case "阳光":
                return AudioParameters.Voice.SUNNY; // 阳光音色
        }
    }
    
    /**
     * 检测文本语言类型
     */
    private String detectLanguageType(String text) {
        if (text == null || text.isEmpty()) {
            return "Chinese";
        }
        
        // 简单的语言检测：检查是否包含中文字符
        boolean hasChinese = text.matches(".*[\u4e00-\u9fa5].*");
        boolean hasEnglish = text.matches(".*[a-zA-Z].*");
        
        if (hasChinese && hasEnglish) {
            return "Mixed"; // 中英混合
        } else if (hasChinese) {
            return "Chinese"; // 中文
        } else if (hasEnglish) {
            return "English"; // 英文
        } else {
            return "Chinese"; // 默认中文
        }
    }
    
    /**
     * 下载音频文件并存储到本地
     */
    private String downloadAndStoreAudio(String audioUrl, String format) throws Exception {
        try {
            // 下载音频文件
            try (InputStream in = new URL(audioUrl).openStream()) {
                // 读取音频数据
                byte[] audioData = in.readAllBytes();
                
                // 将音频数据转换为Base64（用于存储服务）
                String base64Audio = java.util.Base64.getEncoder().encodeToString(audioData);
                
                // 使用文件存储服务保存音频文件
                String localUrl = voiceFileStorageService.storeVoiceFile(
                    "data:audio/" + format + ";base64," + base64Audio, 
                    format, 
                    null // messageId为null，表示这是TTS生成的文件
                );
                
                System.out.println("音频文件已下载并存储: " + localUrl);
                return localUrl;
                
            }
        } catch (Exception e) {
            System.err.println("下载音频文件时出错: " + e.getMessage());
            throw new Exception("音频文件下载失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 估算音频时长（基于文本长度）
     */
    private BigDecimal estimateAudioDuration(String text) {
        if (text == null || text.isEmpty()) {
            return BigDecimal.valueOf(1.0);
        }
        
        // 简单估算：中文约2字符/秒，英文约8字符/秒
        boolean hasChinese = text.matches(".*[\u4e00-\u9fa5].*");
        double charsPerSecond = hasChinese ? 2.5 : 8.0;
        double duration = text.length() / charsPerSecond;
        
        // 最小1秒，最大60秒
        duration = Math.max(1.0, Math.min(60.0, duration));
        
        return BigDecimal.valueOf(duration);
    }
    
    /**
     * 创建模拟TTS结果（降级方案）
     */
    private TextToSpeechVO createMockTTSResult(TextToSpeechDTO textToSpeechDTO, long startTime) {
        TextToSpeechVO result = new TextToSpeechVO();
        result.setAudioUrl("https://example.com/audio/" + System.currentTimeMillis() + ".wav");
        result.setFileSize(1024L * 50); // 50KB
        result.setDuration(BigDecimal.valueOf(textToSpeechDTO.getText().length() * 0.1)); // 估算时长
        result.setFormat(textToSpeechDTO.getFormat());
        result.setProcessTime((int)(System.currentTimeMillis() - startTime));
        return result;
    }
    
    /**
     * 处理音频数据，支持URL和Base64格式，并处理格式转换
     */
    private String processAudioData(String audioData) throws Exception {
        if (audioData == null || audioData.trim().isEmpty()) {
            throw new Exception("音频数据不能为空");
        }
        
        // 如果是data URL格式（Base64编码）
        if (audioData.startsWith("data:audio/")) {
            // 检查是否为WebM格式，如果是则尝试转换或给出警告
            if (audioData.startsWith("data:audio/webm")) {
                System.out.println("⚠️ 检测到WebM格式，阿里云ASR可能不支持，尝试处理...");
                // 尝试转换WebM为WAV格式
                try {
                    String convertedAudio = convertWebmToWav(audioData);
                    System.out.println("✅ WebM格式已转换为WAV格式");
                    return convertedAudio;
                } catch (Exception e) {
                    System.err.println("❌ WebM转换失败: " + e.getMessage());
                    System.out.println("⚠️ 继续使用原始WebM格式，但识别效果可能不佳");
                    // 仍然尝试处理，但可能识别效果不佳
                }
            }
            return audioData;
        }
        
        // 如果是Base64编码（不带前缀）
        if (isBase64(audioData)) {
            return "data:audio/wav;base64," + audioData;
        }
        
        // 如果是URL，检查是否为公网可访问
        if (audioData.startsWith("http://") || audioData.startsWith("https://")) {
            if (audioData.contains("localhost") || audioData.contains("127.0.0.1")) {
                throw new Exception("阿里云无法访问本地URL，请使用公网可访问的URL或Base64编码的音频数据");
            }
            return audioData;
        }
        
        // 其他情况，当作测试数据处理
        throw new Exception("无效的音频数据格式，请使用公网URL或Base64编码的音频数据");
    }
    
    /**
     * 将WebM格式音频转换为WAV格式
     * 注意：这是一个简化的实现，实际项目中建议使用FFmpeg
     */
    private String convertWebmToWav(String webmAudioData) throws Exception {
        // 提取Base64数据
        String base64Data = webmAudioData.substring(webmAudioData.indexOf(",") + 1);
        
        // 解码Base64数据（用于验证）
        java.util.Base64.getDecoder().decode(base64Data);
        
        // 简单的格式转换（这里只是示例，实际应该使用FFmpeg）
        // 由于WebM到WAV的转换比较复杂，这里暂时返回原始数据但修改MIME类型
        // 在实际项目中，建议集成FFmpeg进行真正的格式转换
        
        System.out.println("⚠️ WebM到WAV转换功能需要集成FFmpeg，当前使用原始格式");
        
        // 返回修改了MIME类型的音频数据
        return "data:audio/wav;base64," + base64Data;
    }
    
    /**
     * 检查字符串是否为Base64编码
     */
    private boolean isBase64(String str) {
        if (str == null || str.length() == 0) {
            return false;
        }
        try {
            // 简单的Base64格式检查
            return str.matches("^[A-Za-z0-9+/]*={0,2}$") && str.length() % 4 == 0 && str.length() > 100;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取API密钥（优先使用配置文件，其次使用环境变量）
     */
    private String getApiKey() {
        // 优先使用配置文件中的API密钥
        if (dashscopeApiKey != null && !dashscopeApiKey.trim().isEmpty()) {
            return dashscopeApiKey.trim();
        }
        
        // 其次使用环境变量
        String envApiKey = System.getenv("DASHSCOPE_API_KEY");
        if (envApiKey != null && !envApiKey.trim().isEmpty()) {
            return envApiKey.trim();
        }
        
        return null;
    }

    @Override
    public MessageVO processVoiceMessage(ProcessMessageDTO processMessageDTO) {
        // 1. 语音转文字
        SpeechToTextDTO speechToTextDTO = new SpeechToTextDTO();
        speechToTextDTO.setAudioData(processMessageDTO.getAudioData());
        speechToTextDTO.setFormat(processMessageDTO.getFormat());
        speechToTextDTO.setEnableEmotionDetection(true);

        SpeechToTextVO speechResult = speechToText(speechToTextDTO);

        // 2. 发送消息获取AI回复（包含用户录音URL）
        SendMessageDTO sendMessageDTO = new SendMessageDTO();
        sendMessageDTO.setCharacterId(processMessageDTO.getCharacterId());
        sendMessageDTO.setContent(speechResult.getText());
        sendMessageDTO.setContentType("voice");
        sendMessageDTO.setConversationId(processMessageDTO.getConversationId());
        // 设置用户录音URL（如果提供了的话）
        if (processMessageDTO.getUserVoiceUrl() != null) {
            sendMessageDTO.setVoiceUrl(processMessageDTO.getUserVoiceUrl());
        }

        MessageVO aiReply = messagesService.sendMessageAndGetReply(sendMessageDTO, processMessageDTO.getUserId());

        // 3. 将AI回复转换为语音
        TextToSpeechDTO textToSpeechDTO = new TextToSpeechDTO();
        textToSpeechDTO.setText(aiReply.getContent());
        textToSpeechDTO.setVoiceType("female");
        textToSpeechDTO.setEmotion("neutral");

        TextToSpeechVO voiceResult = textToSpeech(textToSpeechDTO);

        // 4. 更新AI回复消息的语音URL并保存到数据库
        aiReply.setVoiceUrl(voiceResult.getAudioUrl());
        aiReply.setContentType("voice");
        
        // 将语音URL更新到数据库中的AI消息记录
        try {
            Messages aiMessage = messagesService.getById(aiReply.getId());
            if (aiMessage != null) {
                aiMessage.setVoiceUrl(voiceResult.getAudioUrl());
                aiMessage.setContentType("voice");
                messagesService.updateById(aiMessage);
                System.out.println("✅ AI回复语音URL已保存到数据库: " + voiceResult.getAudioUrl());
            } else {
                System.err.println("❌ 未找到AI消息记录，无法更新语音URL");
            }
        } catch (Exception e) {
            System.err.println("❌ 更新AI消息语音URL失败: " + e.getMessage());
            // 不抛出异常，避免影响整个流程
        }

        return aiReply;
    }

    @Override
    public UploadUserAudioVO uploadUserAudio(UploadUserAudioDTO uploadUserAudioDTO) {
        UploadUserAudioVO result = new UploadUserAudioVO();
        
        try {
            // 输入验证
            if (uploadUserAudioDTO.getAudioData() == null || uploadUserAudioDTO.getAudioData().trim().isEmpty()) {
                throw new Exception("音频数据不能为空");
            }
            
            if (uploadUserAudioDTO.getUserId() == null) {
                throw new Exception("用户ID不能为空");
            }

            // 验证音频数据格式
            String audioData = uploadUserAudioDTO.getAudioData();
            if (!isValidAudioData(audioData)) {
                throw new Exception("音频数据格式无效，请使用Base64编码的音频数据");
            }

            // 设置默认格式
            String format = uploadUserAudioDTO.getFormat();
            if (format == null || format.isEmpty()) {
                format = "wav";
            }

            // 检查文件大小 (Base64编码后的数据大小)
            long encodedSize = audioData.length();
            long estimatedFileSize = (long) (encodedSize * 0.75); // Base64解码后约为原大小的75%
            
            if (estimatedFileSize > 10 * 1024 * 1024) { // 10MB限制
                throw new Exception("音频文件过大，请确保文件大小小于10MB");
            }

            // 使用专门的用户录音存储服务
            String voiceUrl = voiceFileStorageService.storeUserVoiceFile(
                audioData, 
                format, 
                uploadUserAudioDTO.getUserId()
            );

            // 从URL中提取文件名
            String fileName = voiceUrl.substring(voiceUrl.lastIndexOf('/') + 1);

            // 计算音频时长（估算）
            BigDecimal duration = calculateAudioDuration(audioData);

            // 构建返回结果
            result.setVoiceUrl(voiceUrl);
            result.setFileSize(estimatedFileSize);
            result.setDuration(duration);
            result.setFormat(format);
            result.setFilePath(fileName);
            result.setUploadTime(java.time.LocalDateTime.now());
            result.setSuccess(true);

            System.out.println(String.format("用户录音上传成功 - 用户ID: %d, 文件: %s, 大小: %d bytes, 时长: %.2f秒", 
                uploadUserAudioDTO.getUserId(), fileName, estimatedFileSize, duration.doubleValue()));

            return result;
            
        } catch (Exception e) {
            System.err.println("用户录音上传失败: " + e.getMessage());
            e.printStackTrace();
            
            // 返回失败结果
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            result.setUploadTime(java.time.LocalDateTime.now());
            
            return result;
        }
    }
    
    /**
     * 验证音频数据是否有效
     */
    private boolean isValidAudioData(String audioData) {
        if (audioData == null || audioData.isEmpty()) {
            return false;
        }
        
        // 检查是否是data URL格式
        if (audioData.startsWith("data:audio/")) {
            return true;
        }
        
        // 检查是否是纯Base64格式
        return isBase64(audioData);
    }
}
